home *** CD-ROM | disk | FTP | other *** search
- # Source Generated with Decompyle++
- # File: in.pyc (Python 2.6)
-
- """Module implementing the chess rules.
-
- To use create an instance of the chess board:
- >>> b = board.ChessBoard()
-
- Board locations can be represented in two forms:
- o A 2-tuple containing the file and rank as integers (see below).
- o A string with the location in SAN format.
-
- e.g. The black king is on the square (4,7) or 'e8'.
-
- The chess board with rank and file numbers:
-
- Black Pieces
-
- +---+---+---+---+---+---+---+---+
- 7 |<R>|<N>|<B>|<Q>|<K>|<B>|<N>|<R>|
- +---+---+---+---+---+---+---+---+
- 6 |<P>|<P>|<P>|<P>|<P>|<P>|<P>|<P>|
- +---+---+---+---+---+---+---+---+
- 5 | | . | | . | | . | | . |
- +---+---+---+---+---+---+---+---+
- 4 | . | | . | | . | | . | |
- +---+---+---+---+---+---+---+---+
- 3 | | . | | . | | . | | . |
- +---+---+---+---+---+---+---+---+
- 2 | . | | . | | . | | . | |
- +---+---+---+---+---+---+---+---+
- 1 |-P-|-P-|-P-|-P-|-P-|-P-|-P-|-P-|
- +---+---+---+---+---+---+---+---+
- 0 |-R-|-N-|-B-|-Q-|-K-|-B-|-N-|-R-|
- +---+---+---+---+---+---+---+---+
- 0 1 2 3 4 5 6 7
-
- White Pieces
-
- Pieces are moved by:
- >>> move = b.movePiece(board.WHITE, 'd1', 'd3')
- If the move is not None then the internal state is updated and the
- next player can move.
- If the result is None then the request is ignored.
-
- A move can be checked if it is legal first by:
- >>> result = b.testMove(board.WHITE, 'd1', 'd3')
- The returns the same values as movePiece() except the internal state
- is never updated.
-
- The location of pieces can be checked using:
- >>> piece = b.getPiece('e1')
- >>> pieces = b.getAlivePieces()
- >>> casualties = b.getDeadPieces()
- The locations are always in the 2-tuple format.
- These methods return references to the ChessPiece objects on the board.
-
- The history of the game can be retrieved by passing a move number to
- the get*() methods. This number is the move count from the game start.
- It also supports negative indexing:
- 0 = board before game starts
- 1 = board after white's first move
- 2 = board after black's first move
- -1 = The last move
- e.g.
- To get the white pieces after whites second move.
- >>> pieces = b.getAlivePieces(3)
-
- The ChessPiece objects are static per board. Thus references can be compared
- between move 0 and move N. Note promoted pieces are a new piece object.
-
- When any piece is moved onPieceMoved() method is called. If the ChessBoard
- class is extended this signal can be picked up by the user. If movePiece()
- or testMove() is called while in this method an exception is raised.
- """
- __author__ = 'Robert Ancell <bob27@users.sourceforge.net>'
- __license__ = 'GNU General Public License Version 2'
- __copyright__ = 'Copyright 2005-2006 Robert Ancell'
- __all__ = [
- 'ChessPiece',
- 'ChessBoard',
- 'Move']
- import bitboard
- WHITE = 'White'
- BLACK = 'Black'
- PAWN = 'P'
- ROOK = 'R'
- KNIGHT = 'N'
- BISHOP = 'B'
- QUEEN = 'Q'
- KING = 'K'
-
- class ChessPiece:
- '''An object representing a chess piece'''
- __colour = None
- __type = None
-
- def __init__(self, colour, type):
- """Constructor for a chess piece.
-
- 'colour' is the piece colour (WHITE or BLACK).
- 'type' is the piece type (PAWN, ROOK, KNIGHT, BISHOP, QUEEN or KING).
- """
- self._ChessPiece__colour = colour
- self._ChessPiece__type = type
-
-
- def getColour(self):
- '''Get the colour of this piece.
-
- Returns WHITE or BLACK.
- '''
- return self._ChessPiece__colour
-
-
- def getType(self):
- '''Get the type of this piece.
-
- Returns PAWN, ROOK, KNIGHT, BISHOP, QUEEN or KING.
- '''
- return self._ChessPiece__type
-
-
- def __str__(self):
- '''Returns a string representation of this piece'''
- return self._ChessPiece__colour + ' ' + self._ChessPiece__type
-
-
- def __repr__(self):
- return '<%s>' % str(self)
-
-
-
- class ChessPlayerState:
- '''
- '''
- canShortCastle = True
- canLongCastle = True
- inCheck = False
-
- def __init__(self, state = None):
- '''
- '''
- if state is None:
- return None
- self.canShortCastle = state.canShortCastle
- self.canLongCastle = state.canLongCastle
-
-
- def __eq__(self, state):
- '''Compare two states are equal'''
- if self.canShortCastle != state.canShortCastle:
- return False
- if self.canLongCastle != state.canLongCastle:
- return False
- return True
-
-
- def __ne__(self, state):
- return not (self == state)
-
-
-
- class Move:
- '''
- '''
- moves = []
- victim = None
- opponentInCheck = False
- opponentCanMove = False
- threeFoldRepetition = False
- fiftyMoveRule = False
-
-
- class ChessBoardState:
- '''
- '''
- moveNumber = 0
- squares = None
- casualties = None
- lastMove = None
- moves = None
- enPassantSquare = None
- whiteState = None
- blackState = None
- fiftyMoveCount = 0
- threeFoldRepetition = False
- whiteBitBoard = 0
- blackBitBoard = 0
- allBitBoard = 0
-
- def __init__(self, lastState = None):
- """Constuctor for storing the state of a chess board.
-
- 'lastState' is the previous board state
- or a dictionary containing the initial state of the board
- or None to start an empty board.
-
- Example:
-
- pawn = ChessPiece(WHITE, PAWN)
- ChessBoardState({'a2': pawn, ...})
-
- Note if a dictionary is provided the casualties will only record the pieces
- killed from this point onwards.
- """
- if lastState is None:
- self.whiteBitBoard = 0
- self.blackBitBoard = 0
- self.allBitBoard = 0
- self.moveNumber = 0
- self.squares = { }
- self.casualties = []
- self.moves = []
- self.whiteState = ChessPlayerState()
- self.blackState = ChessPlayerState()
- elif type(lastState) is dict:
- self.moveNumber = 0
- self.squares = { }
- self.casualties = []
- self.moves = []
- self.whiteBitBoard = 0
- self.blackBitBoard = 0
- self.allBitBoard = 0
- for coord, piece in lastState.iteritems():
- self.squares[coord] = piece
- field = bitboard.LOCATIONS[bitboard.getIndex(coord)]
- self.allBitBoard |= field
-
- self.whiteState = ChessPlayerState()
- self.blackState = ChessPlayerState()
- elif isinstance(lastState, ChessBoardState):
- self.whiteBitBoard = lastState.whiteBitBoard
- self.blackBitBoard = lastState.blackBitBoard
- self.allBitBoard = lastState.allBitBoard
- self.moveNumber = lastState.moveNumber + 1
- self.squares = lastState.squares.copy()
- self.casualties = lastState.casualties[:]
- self.lastMove = lastState.lastMove
- self.moves = lastState.moves[:]
- self.enPassantSquare = lastState.enPassantSquare
- self.whiteState = ChessPlayerState(lastState.whiteState)
- self.blackState = ChessPlayerState(lastState.blackState)
- self.fiftyMoveCount = lastState.fiftyMoveCount
- else:
- raise TypeError('ChessBoardState(oldState) or ChessBoardState({(0,0):pawn, ...})')
- return None if piece.getColour() is WHITE else self
-
-
- def addPiece(self, location, colour, pieceType):
- piece = ChessPiece(colour, pieceType)
- if not self.squares.has_key(location) is False:
- raise AssertionError
- if not type(location) == str:
- raise AssertionError
- self.squares[location] = piece
- field = bitboard.LOCATIONS[bitboard.getIndex(location)]
- self.allBitBoard |= field
- return piece
-
-
- def getPiece(self, location):
- """Get the piece at a given location.
-
- 'location' is the location in algebraic format (string).
-
- Return the piece at this location or None if there is no piece there.
- """
- if not type(location) is str or len(location) == 2:
- raise AssertionError
-
- try:
- return self.squares[location]
- except KeyError:
- len(location) == 2
- len(location) == 2
- return None
-
-
-
- def inCheck(self, colour):
- """Test if the player with the given colour is in check.
-
- 'colour' is the colour of the player to check.
-
- Return True if they are in check (or checkmate) or False otherwise.
- """
- for kingCoord, king in self.squares.iteritems():
- if king.getType() != KING or king.getColour() != colour:
- continue
-
- if self.squareUnderAttack(colour, kingCoord):
- return True
-
- return False
-
-
- def squareUnderAttack(self, colour, location, requirePiece = True):
- """Check if a square is under attack according to FIDE chess rules (Article 3.1)
-
- 'colour' is the colour considered to own this square.
- 'location' is the location to check.
- 'requirePiece' if True only considers this square under attack if there is a piece in it.
-
- Return True if there is an enemy piece that can attach this square.
- """
- if requirePiece and self.getPiece(location) is None:
- return False
- for enemyCoord, enemyPiece in self.squares.iteritems():
- if enemyPiece.getColour() == colour:
- continue
-
- board = ChessBoardState(self)
- if board.movePiece(enemyPiece.getColour(), enemyCoord, location, testCheck = False, applyMove = False):
- return True
-
- return False
-
-
- def canMove(self, colour):
- """Test if the player with the given colour is in checkmate.
-
- 'colour' is the colour of the player to check.
-
- Return True if they are in checkmate or False otherwise.
- """
- for coord, piece in self.squares.iteritems():
- if piece.getColour() != colour:
- continue
-
- for rank in 'abcdefgh':
- for file in '12345678':
- board = ChessBoardState(self)
- if board.movePiece(colour, coord, rank + file, applyMove = False):
- return True
-
-
-
- return False
-
-
- def _getSquareColour(self, coord):
- return {
- 'a8': WHITE,
- 'b8': BLACK,
- 'c8': WHITE,
- 'd8': BLACK,
- 'e8': WHITE,
- 'f8': BLACK,
- 'g8': WHITE,
- 'h8': BLACK,
- 'a7': BLACK,
- 'b7': WHITE,
- 'c7': BLACK,
- 'd7': WHITE,
- 'e7': BLACK,
- 'f7': WHITE,
- 'g7': BLACK,
- 'h7': WHITE,
- 'a6': WHITE,
- 'b6': BLACK,
- 'c6': WHITE,
- 'd6': BLACK,
- 'e6': WHITE,
- 'f6': BLACK,
- 'g6': WHITE,
- 'h6': BLACK,
- 'a5': BLACK,
- 'b5': WHITE,
- 'c5': BLACK,
- 'd5': WHITE,
- 'e5': BLACK,
- 'f5': WHITE,
- 'g5': BLACK,
- 'h5': WHITE,
- 'a4': WHITE,
- 'b4': BLACK,
- 'c4': WHITE,
- 'd4': BLACK,
- 'e4': WHITE,
- 'f4': BLACK,
- 'g4': WHITE,
- 'h4': BLACK,
- 'a3': BLACK,
- 'b3': WHITE,
- 'c3': BLACK,
- 'd3': WHITE,
- 'e3': BLACK,
- 'f3': WHITE,
- 'g3': BLACK,
- 'h3': WHITE,
- 'a2': WHITE,
- 'b2': BLACK,
- 'c2': WHITE,
- 'd2': BLACK,
- 'e2': WHITE,
- 'f2': BLACK,
- 'g2': WHITE,
- 'h2': BLACK,
- 'a1': BLACK,
- 'b1': WHITE,
- 'c1': BLACK,
- 'd1': WHITE,
- 'e1': BLACK,
- 'f1': WHITE,
- 'g1': BLACK,
- 'h1': WHITE }[coord]
-
-
- def sufficientMaterial(self):
- '''Test if there are sufficient pieces to be able to perform checkmate.
-
- Return True if sufficient pieces to make checkmate or False otherwise.
- '''
- knightCount = 0
- bishopCount = 0
- for coord, piece in self.squares.iteritems():
- pieceType = piece.getType()
- if pieceType == PAWN and pieceType == ROOK or pieceType == QUEEN:
- return True
- if pieceType == BISHOP:
- bishopCount += 1
- colour = self._getSquareColour(coord)
- bishopSquareColour = colour
- continue
- None if bishopCount > 1 else None if pieceType == KNIGHT else pieceType == QUEEN
-
- return False
-
- allowedMoves = {
- WHITE: {
- PAWN: bitboard.WHITE_PAWN_MOVES,
- ROOK: bitboard.ROOK_MOVES,
- BISHOP: bitboard.BISHOP_MOVES,
- KNIGHT: bitboard.KNIGHT_MOVES,
- QUEEN: bitboard.QUEEN_MOVES,
- KING: bitboard.WHITE_KING_MOVES },
- BLACK: {
- PAWN: bitboard.BLACK_PAWN_MOVES,
- ROOK: bitboard.ROOK_MOVES,
- BISHOP: bitboard.BISHOP_MOVES,
- KNIGHT: bitboard.KNIGHT_MOVES,
- QUEEN: bitboard.QUEEN_MOVES,
- KING: bitboard.BLACK_KING_MOVES } }
-
- def movePiece(self, colour, start, end, promotionType = QUEEN, testCheck = True, allowSuicide = False, applyMove = True):
- """Move a piece.
-
- 'colour' is the colour of the player moving.
- 'start' is a the location to move from in algebraic format (string).
- 'end' is a the location to move to in algebraic format (string).
- 'promotionType' is the type of piece to promote to if required.
- 'testCheck' is a flag to control if the opponent will be in check after this move.
- 'allowSuicide' if True means a move is considered valid even
- if it would put the moving player in check.
- 'applyMove' is a flag to control if the move is applied to the board (True) or just tested (False).
-
- Returns the pieces moved in the form (result, moves).
- The moves are a list containing tuples of the form (piece, start, end). If a piece was removed
- 'end' is None. If the result is successful the pieces on the board are modified.
- If the move is illegal None is returned.
- """
- if not promotionType is not KING:
- raise AssertionError
- if not type(start) is str or len(start) == 2:
- raise AssertionError
- if not type(end) is str or len(end) == 2:
- raise AssertionError
-
- try:
- piece = self.squares[start]
- except KeyError:
- len(end) == 2
- len(end) == 2
- len(start) == 2
- return None
- promotionType is not KING
-
- if piece.getColour() is not colour:
- return None
- startIndex = bitboard.getIndex(start)
- endIndex = bitboard.getIndex(end)
- field = self.allowedMoves[colour][piece.getType()]
- if field[startIndex] & bitboard.LOCATIONS[endIndex] == 0:
- return None
- if self.allBitBoard & bitboard.INBETWEEN_SQUARES[startIndex][endIndex]:
- return None
- if colour is WHITE:
- enemyColour = BLACK
- playerState = self.whiteState
- elif colour is BLACK:
- enemyColour = WHITE
- playerState = self.blackState
- elif not False:
- raise AssertionError
- piece.getColour() is not colour
- originalPlayerState = ChessPlayerState(playerState)
- whiteBitBoard = self.whiteBitBoard
- blackBitBoard = self.blackBitBoard
- allBitBoard = self.allBitBoard
-
- try:
- target = self.squares[end]
- if target.getColour() == colour:
- return None
- except KeyError:
- len(end) == 2
- len(end) == 2
- len(start) == 2
- target = None
- except:
- promotionType is not KING
-
- victim = target
- if colour == BLACK:
- baseFile = '8'
- else:
- baseFile = '1'
- enPassantSquare = None
- moves = []
- if piece.getType() is KING:
- shortCastle = ('e' + baseFile, 'g' + baseFile)
- longCastle = ('e' + baseFile, 'c' + baseFile)
- playerState.canShortCastle = False
- playerState.canLongCastle = False
- moves.append((piece, start, end, False))
- elif piece.getType() is ROOK:
- if start == 'a' + baseFile:
- playerState.canLongCastle = False
- elif start == 'h' + baseFile:
- playerState.canShortCastle = False
-
- moves.append((piece, start, end, False))
- elif piece.getType() is PAWN:
- if baseFile == '1':
- pawnFile = '2'
- marchFile = '3'
- farFile = '8'
- else:
- pawnFile = '7'
- marchFile = '6'
- farFile = '1'
- if (start[1] == '2' or end[1] == '4' or start[1] == '7') and end[1] == '5':
- enPassantSquare = start[0] + marchFile
-
- if start[0] != end[0]:
- if victim is None:
- if end != self.enPassantSquare:
- return None
- moves.append((self.lastMove[0], self.lastMove[2], self.lastMove[2], True))
-
- elif victim is not None:
- return None
- if end[1] == farFile:
- moves.append((piece, start, end, True))
- moves.append((ChessPiece(colour, promotionType), None, end, False))
- else:
- moves.append((piece, start, end, False))
- else:
- moves.append((piece, start, end, False))
- oldLastMove = self.lastMove
- self.lastMove = (piece, start, end)
- oldEnPassantSquare = self.enPassantSquare
- self.enPassantSquare = enPassantSquare
- if victim is not None:
- moves.append((victim, end, end, True))
-
- for p, s, e, d in moves:
- if s is None:
- continue
-
- self.squares.pop(s)
- field = bitboard.LOCATIONS[bitboard.getIndex(s)]
- self.whiteBitBoard &= ~field
- self.blackBitBoard &= ~field
- self.allBitBoard &= ~field
-
- for p, s, e, d in moves:
- self.squares[e] = p
- field = bitboard.LOCATIONS[bitboard.getIndex(e)]
- self.allBitBoard |= field
-
- result = moves
- return result
-
-
- def __eq__(self, board):
- '''Compare if two boards are the same'''
- if len(self.squares) != len(board.squares):
- return False
- if self.enPassantSquare != board.enPassantSquare:
- return False
- if self.whiteState != board.whiteState or self.blackState != board.blackState:
- return False
- for coord, piece in self.squares.iteritems():
-
- try:
- p = board.squares[coord]
- except KeyError:
- self.blackState != board.blackState
- self.blackState != board.blackState
- self.enPassantSquare != board.enPassantSquare
- return False
- len(self.squares) != len(board.squares)
-
- if piece.getType() is not p.getType() or piece.getColour() is not p.getColour():
- return False
-
- return True
-
-
- def __ne__(self, board):
- return not (self == board)
-
-
- def __str__(self):
- '''Covert the board state to a string'''
- out = ''
- blackSquare = False
- for file in '87654321':
- out += ' +---+---+---+---+---+---+---+---+\n'
- out += ' ' + file + ' |'
- blackSquare = not blackSquare
- for rank in 'abcdefgh':
- blackSquare = not blackSquare
-
- try:
- piece = self.squares[rank + file]
- except:
- piece = None
-
- if piece is None:
- if blackSquare:
- out += ' . '
- else:
- out += ' '
- else:
- s = piece.getType()
- if piece.getColour() is WHITE:
- s = '-' + s + '-'
- elif piece.getColour() is BLACK:
- s = '<' + s + '>'
- elif not False:
- raise AssertionError
- out += s
- out += '|'
-
- out += '\n'
-
- out += ' +---+---+---+---+---+---+---+---+\n'
- out += ' a b c d e f g h'
- return out
-
-
-
- class ChessBoard:
- '''An object representing a chess board.
-
- This class contains a chess board and all its previous states.
- '''
-
- def __init__(self, initialState = None):
- '''Constructor for a chess board'''
- self._ChessBoard__inCallback = False
- if initialState is None:
- self._ChessBoard__resetBoard()
- else:
- self._ChessBoard__boardStates = [
- initialState]
-
-
- def onPieceMoved(self, piece, start, end, delete):
- """Called when a piece is moved on the chess board.
-
- 'piece' is the piece being moved.
- 'start' is the start location of the piece (tuple (file,rank) or None if the piece is being created.
- 'end' is the end location of the piece (tuple (file,rank))
- 'delete' is a flag to show if the piece should be deleted when it arrives there (boolean).
- """
- pass
-
-
- def getPiece(self, location, moveNumber = -1):
- """Get the piece at a given location.
-
- 'location' is the board location to check in algebraic format (string).
- 'moveNumber' is the move to get the pieces from (integer).
-
- Return the piece (ChessPiece) at this location or None if there is no piece there.
- Raises an IndexError exception if moveNumber is invalid.
- """
- return self._ChessBoard__boardStates[moveNumber].getPiece(location)
-
-
- def getAlivePieces(self, moveNumber = -1):
- """Get the alive pieces on the board.
-
- 'moveNumber' is the move to get the pieces from (integer).
-
- Returns a dictionary of the alive pieces (ChessPiece) keyed by location.
- Raises an IndexError exception if moveNumber is invalid.
- """
- state = self._ChessBoard__boardStates[moveNumber]
- return state.squares.copy()
-
-
- def getDeadPieces(self, moveNumber = -1):
- """Get the dead pieces from the game.
-
- 'moveNumber' is the move to get the pieces from (integer).
-
- Returns a list of the pieces (ChessPiece) in the order they were killed.
- Raises an IndexError exception if moveNumber is invalid.
- """
- state = self._ChessBoard__boardStates[moveNumber]
- return state.casualties[:]
-
-
- def testMove(self, colour, start, end, promotionType = QUEEN, allowSuicide = False, moveNumber = -1):
- """Test if a move is allowed.
-
- 'colour' is the colour of the player moving.
- 'start' is a the location to move from in algebraic format (string).
- 'end' is a the location to move to in algebraic format (string).
- 'allowSuicide' if True means a move is considered valid even
- if it would put the moving player in check. This is
- provided for SAN move calculation.
-
- Returns the same as movePiece() except the move is not recorded.
- """
- return self.movePiece(colour, start, end, promotionType = promotionType, allowSuicide = allowSuicide, test = True, moveNumber = moveNumber)
-
-
- def squareUnderAttack(self, colour, location, moveNumber = -1):
- state = self._ChessBoard__boardStates[moveNumber]
- return state.squareUnderAttack(colour, location)
-
-
- def sufficientMaterial(self, moveNumber = -1):
- '''Test if there are sufficient pieces to be able to perform checkmate.
-
- Return True if sufficient pieces to make checkmate or False otherwise.
- '''
- state = self._ChessBoard__boardStates[moveNumber]
- return state.sufficientMaterial()
-
-
- def movePiece(self, colour, start, end, promotionType = QUEEN, allowSuicide = False, test = False, moveNumber = -1):
- """Move a piece.
-
- 'colour' is the colour of the player moving.
- 'start' is a the location to move from in algebraic format (string).
- 'end' is a the location to move to in algebraic format (string).
- 'allowSuicide' if True means a move is considered valid even
- if it would put the moving player in check. This is
- provided for SAN move calculation.
-
- Return information about the move performed (Move) or None if the move is illegal.
- """
- if not self._ChessBoard__inCallback is False:
- raise AssertionError
- state = ChessBoardState(self._ChessBoard__boardStates[moveNumber])
- if not state.movePiece(colour, start, end, promotionType = promotionType, allowSuicide = False):
- return None
- victim = None
- for piece, start, end, delete in state.moves:
- if not test:
- self._ChessBoard__onPieceMoved(piece, start, end, delete)
- continue
- None if delete and piece.getColour() != colour else self._ChessBoard__inCallback is False
-
- sameCount = 0
- for s in self._ChessBoard__boardStates:
- if state == s:
- sameCount += 1
- if sameCount >= 2:
- state.threeFoldRepetition = True
- break
-
- sameCount >= 2
-
- if colour is WHITE:
- opponentColour = BLACK
- else:
- opponentColour = WHITE
- if not test:
- self._ChessBoard__boardStates.append(state)
-
- move = Move()
- move.moves = state.moves
- move.victim = victim
- move.opponentInCheck = state.inCheck(opponentColour)
- move.opponentCanMove = state.canMove(opponentColour)
- move.threeFoldRepetition = state.threeFoldRepetition
- move.fiftyMoveRule = state.fiftyMoveCount >= 50
- return move
-
-
- def undo(self):
- '''Undo the last move'''
- undoState = self._ChessBoard__boardStates[-1]
- self._ChessBoard__boardStates = self._ChessBoard__boardStates[:-1]
- for piece, start, end, delete in undoState.moves:
- self._ChessBoard__onPieceMoved(piece, end, start, False)
-
-
-
- def __str__(self):
- '''Returns a representation of the current board state'''
- return str(self._ChessBoard__boardStates[-1])
-
-
- def __onPieceMoved(self, piece, start, end, delete):
- '''
- '''
- self._ChessBoard__inCallback = True
- self.onPieceMoved(piece, start, end, delete)
- self._ChessBoard__inCallback = False
-
-
- def __addPiece(self, state, colour, pieceType, location):
- """Add a piece into the board.
-
- 'state' is the board state to add the piece into.
- 'colour' is the colour of the piece.
- 'pieceType' is the type of piece to add.
- 'location' is the start location of the piece in algebraic format (string).
- """
- piece = state.addPiece(location, colour, pieceType)
- self._ChessBoard__onPieceMoved(piece, None, location, False)
-
-
- def __resetBoard(self):
- '''Set up the chess board.
-
- Any exisiting states are deleted.
- The user will be notified of the piece deletions.
- '''
- initialState = ChessBoardState()
- self._ChessBoard__boardStates = [
- initialState]
- secondRank = [
- ('a', ROOK),
- ('b', KNIGHT),
- ('c', BISHOP),
- ('d', QUEEN),
- ('e', KING),
- ('f', BISHOP),
- ('g', KNIGHT),
- ('h', ROOK)]
- for rank, piece in secondRank:
- self._ChessBoard__addPiece(initialState, WHITE, piece, rank + '1')
- self._ChessBoard__addPiece(initialState, WHITE, PAWN, rank + '2')
- self._ChessBoard__addPiece(initialState, BLACK, piece, rank + '8')
- self._ChessBoard__addPiece(initialState, BLACK, PAWN, rank + '7')
-
-
-
- if __name__ == '__main__':
- p = ChessPiece(WHITE, QUEEN)
- print p
- print repr(p)
-
- def test_moves(name, colour, start, whitePieces, blackPieces, validResults):
- print name + ':'
- board = { }
- for coord, piece in whitePieces.iteritems():
- board[coord] = ChessPiece(WHITE, piece)
-
- for coord, piece in blackPieces.iteritems():
- board[coord] = ChessPiece(BLACK, piece)
-
- s = ChessBoardState(board)
- resultMatrix = { }
- for rank in 'abcdefgh':
- for file in '12345678':
- end = rank + file
-
- try:
- expected = validResults[end]
- except:
- expected = None
-
- x = ChessBoardState(s)
- b = ChessBoard(x)
- move = b.movePiece(colour, start, end)
- resultMatrix[end] = move
- isAllowed = validResults.__contains__(end)
- if (move is None or isAllowed or move is not None) and not isAllowed:
- print 'Unexpected result: ' + str(start) + '-' + str(end)
- continue
-
-
- out = ''
- for file in '87654321':
- out += ' +---+---+---+---+---+---+---+---+\n'
- out += ' ' + file + ' |'
- for rank in 'abcdefgh':
- coord = rank + file
-
- try:
- move = resultMatrix[coord]
- except:
- p = 'X'
-
- if move is not None and move.opponentInCheck:
- if move.opponentCanMove:
- p = '+'
- else:
- p = '#'
- else:
- p = ' '
- piece = s.getPiece(rank + file)
- if piece is not None:
- p = piece.getType()
-
- piece = s.getPiece(rank + file)
- if piece is None:
- box = ' ' + p + ' '
- elif piece.getColour() is BLACK:
- box = '=' + p + '='
- elif piece.getColour() is WHITE:
- box = '-' + p + '-'
-
- out += box + '|'
-
- out += '\n'
-
- out += ' +---+---+---+---+---+---+---+---+\n'
- out += ' a b c d e f g h\n'
- print out
-
- c = ChessBoard()
- result = ' +---+---+---+---+---+---+---+---+\n 8 |<R>|<N>|<B>|<Q>|<K>|<B>|<N>|<R>|\n +---+---+---+---+---+---+---+---+\n 7 |<P>|<P>|<P>|<P>|<P>|<P>|<P>|<P>|\n +---+---+---+---+---+---+---+---+\n 6 | | . | | . | | . | | . |\n +---+---+---+---+---+---+---+---+\n 5 | . | | . | | . | | . | |\n +---+---+---+---+---+---+---+---+\n 4 | | . | | . | | . | | . |\n +---+---+---+---+---+---+---+---+\n 3 | . | | . | | . | | . | |\n +---+---+---+---+---+---+---+---+\n 2 |-P-|-P-|-P-|-P-|-P-|-P-|-P-|-P-|\n +---+---+---+---+---+---+---+---+\n 1 |-R-|-N-|-B-|-Q-|-K-|-B-|-N-|-R-|\n +---+---+---+---+---+---+---+---+\n a b c d e f g h'
- if str(c) != result:
- print 'Got:'
- print str(c)
- print
- print 'Expected:'
- print result
-
- print str(c)
- test_moves('Pawn', WHITE, 'e4', {
- 'e4': PAWN }, { }, [
- 'e5'])
- test_moves('Pawn on base rank', WHITE, 'e2', {
- 'e2': PAWN }, { }, [
- 'e3',
- 'e4'])
- test_moves('Rook', WHITE, 'e4', {
- 'e4': ROOK }, { }, [
- 'a4',
- 'b4',
- 'c4',
- 'd4',
- 'f4',
- 'g4',
- 'h4',
- 'e1',
- 'e2',
- 'e3',
- 'e5',
- 'e6',
- 'e7',
- 'e8'])
- test_moves('Knight', WHITE, 'e4', {
- 'e4': KNIGHT }, { }, [
- 'd6',
- 'f6',
- 'g5',
- 'g3',
- 'f2',
- 'd2',
- 'c3',
- 'c5'])
- test_moves('Bishop', WHITE, 'e4', {
- 'e4': BISHOP }, { }, [
- 'a8',
- 'b7',
- 'c6',
- 'd5',
- 'f3',
- 'g2',
- 'h1',
- 'b1',
- 'c2',
- 'd3',
- 'f5',
- 'g6',
- 'h7'])
- test_moves('Queen', WHITE, 'e4', {
- 'e4': QUEEN }, { }, [
- 'a8',
- 'b7',
- 'c6',
- 'd5',
- 'f3',
- 'g2',
- 'h1',
- 'b1',
- 'c2',
- 'd3',
- 'f5',
- 'g6',
- 'h7',
- 'a4',
- 'b4',
- 'c4',
- 'd4',
- 'f4',
- 'g4',
- 'h4',
- 'e1',
- 'e2',
- 'e3',
- 'e5',
- 'e6',
- 'e7',
- 'e8'])
- test_moves('King', WHITE, 'e4', {
- 'e4': KING }, { }, [
- 'd5',
- 'e5',
- 'f5',
- 'd4',
- 'f4',
- 'd3',
- 'e3',
- 'f3'])
- test_moves('Blocking', WHITE, 'd4', {
- 'd4': QUEEN,
- 'e4': PAWN,
- 'd6': KNIGHT,
- 'd2': ROOK,
- 'f6': BISHOP,
- 'e3': BISHOP,
- 'b4': PAWN,
- 'b2': PAWN,
- 'a7': PAWN }, {
- 'd8': KNIGHT,
- 'c4': PAWN }, [
- 'b6',
- 'c5',
- 'd5',
- 'e5',
- 'c4',
- 'c3',
- 'd3'])
- test_moves('Moving into check', WHITE, 'e4', {
- 'e4': KING }, {
- 'e6': ROOK }, [
- 'd5',
- 'f5',
- 'd4',
- 'f4',
- 'd3',
- 'f3'])
- test_moves('Held in check', WHITE, 'e4', {
- 'e4': KING }, {
- 'f6': ROOK }, [
- 'd5',
- 'e5',
- 'd4',
- 'd3',
- 'e3'])
- test_moves('Putting opponent in check', WHITE, 'd3', {
- 'd3': BISHOP }, {
- 'd7': KING,
- 'd6': ROOK }, [
- 'a6',
- 'b5',
- 'c4',
- 'e2',
- 'f1',
- 'b1',
- 'c2',
- 'e4',
- 'f5',
- 'g6',
- 'h7'])
- test_moves('Putting opponent into checkmate', WHITE, 'c1', {
- 'c1': BISHOP,
- 'g1': ROOK,
- 'a7': ROOK }, {
- 'h8': KING }, [
- 'b2',
- 'a3',
- 'd2',
- 'e3',
- 'f4',
- 'g5',
- 'h6'])
- test_moves('Cannot put opponent in check if we would go into check', WHITE, 'd3', {
- 'd2': KING,
- 'd3': BISHOP }, {
- 'd7': KING,
- 'd6': ROOK }, [])
- test_moves('Castle1', WHITE, 'e1', {
- 'e1': KING,
- 'a1': ROOK }, { }, [
- 'd2',
- 'e2',
- 'f2',
- 'd1',
- 'f1',
- 'c1'])
- test_moves('Castle2', BLACK, 'e8', { }, {
- 'e8': KING,
- 'h8': ROOK }, [
- 'd7',
- 'e7',
- 'f7',
- 'd8',
- 'f8',
- 'g8'])
- test_moves('Castle in check1', BLACK, 'e8', {
- 'f1': ROOK }, {
- 'e8': KING,
- 'h8': ROOK }, [
- 'd7',
- 'e7',
- 'd8'])
- test_moves('Castle in check2', BLACK, 'e8', {
- 'e1': ROOK }, {
- 'e8': KING,
- 'h8': ROOK }, [
- 'd7',
- 'd8',
- 'f7',
- 'f8'])
- test_moves('Castle in check3', BLACK, 'e8', {
- 'h1': ROOK }, {
- 'e8': KING,
- 'h8': ROOK }, [
- 'd7',
- 'e7',
- 'f7',
- 'd8',
- 'f8',
- 'g8'])
-
-